{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configurations for Colab"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "IN_COLAB = \"google.colab\" in sys.modules\n",
    "\n",
    "if IN_COLAB:\n",
    "    !apt install python-opengl\n",
    "    !apt install ffmpeg\n",
    "    !apt install xvfb\n",
    "    !pip install pyvirtualdisplay\n",
    "    from pyvirtualdisplay import Display\n",
    "    \n",
    "    # Start virtual display\n",
    "    dis = Display(visible=0, size=(400, 400))\n",
    "    dis.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 03. Prioritized Experience Replay (PER)\n",
    "\n",
    "[T. Schaul et al., \"Prioritized Experience Replay.\" arXiv preprint arXiv:1511.05952, 2015.](https://arxiv.org/pdf/1511.05952.pdf)\n",
    "\n",
    "Using a replay memory leads to design choices at two levels: which experiences to store, and which experiences to replay (and how to do so). This paper addresses only the latter: making the most effective use of the replay memory for learning, assuming that its contents are outside of our control.\n",
    "\n",
    "The central component of prioritized replay is the criterion by which the importance of each transition is measured. A reasonable approach is to use the magnitude of a transition’s TD error $\\delta$, which indicates how ‘surprising’\n",
    "or unexpected the transition is. This algorithm stores the last encountered TD error along with each transition in the replay memory. The transition with the largest absolute TD error is replayed from the memory. A Q-learning update\n",
    "is applied to this transition, which updates the weights in proportion to the TD error. One thing to note that new transitions arrive without a known TD-error, so it puts them at maximal priority in order to guarantee that all experience is seen at least once. (see *store* method)\n",
    "\n",
    "We might use 2 ideas to deal with TD-error: 1. greedy TD-error prioritization, 2. stochastic prioritization. However, greedy TD-error prioritization has a severe drawback. Greedy prioritization focuses on a small subset of the experience: errors shrink slowly, especially when using function approximation, meaning that the initially high error transitions get replayed frequently. This lack of diversity that makes the system prone to over-fitting. To overcome this issue, we will use a stochastic sampling method that interpolates between pure greedy prioritization and uniform random sampling.\n",
    "\n",
    "$$\n",
    "P(i) = \\frac{p_i^{\\alpha}}{\\sum_k p_k^{\\alpha}}\n",
    "$$\n",
    "\n",
    "where $p_i > 0$ is the priority of transition $i$. The exponent $\\alpha$ determines how much prioritization is used, with $\\alpha = 0$ corresponding to the uniform case. In practice, we use additional term $\\epsilon$ in order to guarantee all transactions can be possibly sampled: $p_i = |\\delta_i| + \\epsilon$, where $\\epsilon$ is a small positive constant.\n",
    "\n",
    "One more. Let's recall one of the main ideas of DQN. To remove correlation of observations, it uses uniformly random sampling from the replay buffer. Prioritized replay introduces bias because it doesn't sample experiences uniformly at random due to the sampling proportion correspoding to TD-error. We can correct this bias by using importance-sampling (IS) weights\n",
    "\n",
    "$$\n",
    "w_i = \\big( \\frac{1}{N} \\cdot \\frac{1}{P(i)} \\big)^\\beta\n",
    "$$\n",
    "\n",
    "that fully compensates for the non-uniform probabilities $P(i)$ if $\\beta = 1$. These weights can be folded into the Q-learning update by using $w_i\\delta_i$ instead of $\\delta_i$. In typical reinforcement learning scenarios, the unbiased nature of the updates is most important near convergence at the end of training, We therefore exploit the flexibility of annealing the amount of importance-sampling correction over time, by defining a schedule on the exponent $\\beta$ that reaches 1 only at the end of learning. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import random\n",
    "from typing import Dict, List, Tuple\n",
    "\n",
    "import gym\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from IPython.display import clear_output\n",
    "\n",
    "if IN_COLAB and not os.path.exists(\"segment_tree.py\"):\n",
    "    # download segment tree module\n",
    "    !wget https://raw.githubusercontent.com/curt-park/rainbow-is-all-you-need/master/segment_tree.py\n",
    "        \n",
    "from segment_tree import MinSegmentTree, SumSegmentTree"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replay buffer\n",
    "\n",
    "Please see *01.dqn.ipynb* for detailed description."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    \"\"\"A simple numpy replay buffer.\"\"\"\n",
    "\n",
    "    def __init__(self, obs_dim: int, size: int, batch_size: int = 32):\n",
    "        self.obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.next_obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.acts_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.rews_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.done_buf = np.zeros(size, dtype=np.float32)\n",
    "        self.max_size, self.batch_size = size, batch_size\n",
    "        self.ptr, self.size, = 0, 0\n",
    "\n",
    "    def store(\n",
    "        self,\n",
    "        obs: np.ndarray,\n",
    "        act: np.ndarray, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool,\n",
    "    ):\n",
    "        self.obs_buf[self.ptr] = obs\n",
    "        self.next_obs_buf[self.ptr] = next_obs\n",
    "        self.acts_buf[self.ptr] = act\n",
    "        self.rews_buf[self.ptr] = rew\n",
    "        self.done_buf[self.ptr] = done\n",
    "        self.ptr = (self.ptr + 1) % self.max_size\n",
    "        self.size = min(self.size + 1, self.max_size)\n",
    "\n",
    "    def sample_batch(self) -> Dict[str, np.ndarray]:\n",
    "        idxs = np.random.choice(self.size, size=self.batch_size, replace=False)\n",
    "        return dict(obs=self.obs_buf[idxs],\n",
    "                    next_obs=self.next_obs_buf[idxs],\n",
    "                    acts=self.acts_buf[idxs],\n",
    "                    rews=self.rews_buf[idxs],\n",
    "                    done=self.done_buf[idxs])\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self.size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prioritized replay Buffer\n",
    "\n",
    "The key concept of PER's implementation is *Segment Tree*. It efficiently stores and samples transitions while managing the priorities of them. We recommend you understand how it works before you move on. Here are references for you:\n",
    "\n",
    "- In Korean: https://mrsyee.github.io/rl/2019/01/25/PER-sumtree/\n",
    "- In English: https://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PrioritizedReplayBuffer(ReplayBuffer):\n",
    "    \"\"\"Prioritized Replay buffer.\n",
    "    \n",
    "    Attributes:\n",
    "        max_priority (float): max priority\n",
    "        tree_ptr (int): next index of tree\n",
    "        alpha (float): alpha parameter for prioritized replay buffer\n",
    "        sum_tree (SumSegmentTree): sum tree for prior\n",
    "        min_tree (MinSegmentTree): min tree for min prior to get max weight\n",
    "        \n",
    "    \"\"\"\n",
    "    \n",
    "    def __init__(\n",
    "        self, \n",
    "        obs_dim: int,\n",
    "        size: int, \n",
    "        batch_size: int = 32, \n",
    "        alpha: float = 0.6\n",
    "    ):\n",
    "        \"\"\"Initialization.\"\"\"\n",
    "        assert alpha >= 0\n",
    "        \n",
    "        super(PrioritizedReplayBuffer, self).__init__(obs_dim, size, batch_size)\n",
    "        self.max_priority, self.tree_ptr = 1.0, 0\n",
    "        self.alpha = alpha\n",
    "        \n",
    "        # capacity must be positive and a power of 2.\n",
    "        tree_capacity = 1\n",
    "        while tree_capacity < self.max_size:\n",
    "            tree_capacity *= 2\n",
    "\n",
    "        self.sum_tree = SumSegmentTree(tree_capacity)\n",
    "        self.min_tree = MinSegmentTree(tree_capacity)\n",
    "        \n",
    "    def store(\n",
    "        self, \n",
    "        obs: np.ndarray, \n",
    "        act: int, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool\n",
    "    ):\n",
    "        \"\"\"Store experience and priority.\"\"\"\n",
    "        super().store(obs, act, rew, next_obs, done)\n",
    "        \n",
    "        self.sum_tree[self.tree_ptr] = self.max_priority ** self.alpha\n",
    "        self.min_tree[self.tree_ptr] = self.max_priority ** self.alpha\n",
    "        self.tree_ptr = (self.tree_ptr + 1) % self.max_size\n",
    "\n",
    "    def sample_batch(self, beta: float = 0.4) -> Dict[str, np.ndarray]:\n",
    "        \"\"\"Sample a batch of experiences.\"\"\"\n",
    "        assert len(self) >= self.batch_size\n",
    "        assert beta > 0\n",
    "        \n",
    "        indices = self._sample_proportional()\n",
    "        \n",
    "        obs = self.obs_buf[indices]\n",
    "        next_obs = self.next_obs_buf[indices]\n",
    "        acts = self.acts_buf[indices]\n",
    "        rews = self.rews_buf[indices]\n",
    "        done = self.done_buf[indices]\n",
    "        weights = np.array([self._calculate_weight(i, beta) for i in indices])\n",
    "        \n",
    "        return dict(\n",
    "            obs=obs,\n",
    "            next_obs=next_obs,\n",
    "            acts=acts,\n",
    "            rews=rews,\n",
    "            done=done,\n",
    "            weights=weights,\n",
    "            indices=indices,\n",
    "        )\n",
    "        \n",
    "    def update_priorities(self, indices: List[int], priorities: np.ndarray):\n",
    "        \"\"\"Update priorities of sampled transitions.\"\"\"\n",
    "        assert len(indices) == len(priorities)\n",
    "\n",
    "        for idx, priority in zip(indices, priorities):\n",
    "            assert priority > 0\n",
    "            assert 0 <= idx < len(self)\n",
    "\n",
    "            self.sum_tree[idx] = priority ** self.alpha\n",
    "            self.min_tree[idx] = priority ** self.alpha\n",
    "\n",
    "            self.max_priority = max(self.max_priority, priority)\n",
    "            \n",
    "    def _sample_proportional(self) -> List[int]:\n",
    "        \"\"\"Sample indices based on proportions.\"\"\"\n",
    "        indices = []\n",
    "        p_total = self.sum_tree.sum(0, len(self) - 1)\n",
    "        segment = p_total / self.batch_size\n",
    "        \n",
    "        for i in range(self.batch_size):\n",
    "            a = segment * i\n",
    "            b = segment * (i + 1)\n",
    "            upperbound = random.uniform(a, b)\n",
    "            idx = self.sum_tree.retrieve(upperbound)\n",
    "            indices.append(idx)\n",
    "            \n",
    "        return indices\n",
    "    \n",
    "    def _calculate_weight(self, idx: int, beta: float):\n",
    "        \"\"\"Calculate the weight of the experience at idx.\"\"\"\n",
    "        # get max weight\n",
    "        p_min = self.min_tree.min() / self.sum_tree.sum()\n",
    "        max_weight = (p_min * len(self)) ** (-beta)\n",
    "        \n",
    "        # calculate weights\n",
    "        p_sample = self.sum_tree[idx] / self.sum_tree.sum()\n",
    "        weight = (p_sample * len(self)) ** (-beta)\n",
    "        weight = weight / max_weight\n",
    "        \n",
    "        return weight"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Network\n",
    "\n",
    "We are going to use a simple network architecture with three fully connected layers and two non-linearity functions (ReLU)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Network(nn.Module):\n",
    "    def __init__(self, in_dim: int, out_dim: int):\n",
    "        \"\"\"Initialization.\"\"\"\n",
    "        super(Network, self).__init__()\n",
    "\n",
    "        self.layers = nn.Sequential(\n",
    "            nn.Linear(in_dim, 128), \n",
    "            nn.ReLU(),\n",
    "            nn.Linear(128, 128), \n",
    "            nn.ReLU(), \n",
    "            nn.Linear(128, out_dim)\n",
    "        )\n",
    "\n",
    "    def forward(self, x: torch.Tensor) -> torch.Tensor:\n",
    "        \"\"\"Forward method implementation.\"\"\"\n",
    "        return self.layers(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DQN + PER Agent\n",
    "\n",
    "Here is a summary of DQNAgent class.\n",
    "\n",
    "| Method           | Note                                                 |\n",
    "| ---              | ---                                                  |\n",
    "|select_action     | select an action from the input state.               |\n",
    "|step              | take an action and return the response of the env.   |\n",
    "|compute_dqn_loss  | return dqn loss.                                     |\n",
    "|update_model      | update the model by gradient descent.                |\n",
    "|target_hard_update| hard update from the local model to the target model.|\n",
    "|train             | train the agent during num_frames.                   |\n",
    "|test              | test the agent (1 episode).                          |\n",
    "|plot              | plot the training progresses.                        |\n",
    "\n",
    "\n",
    "All differences from pure DQN are noted with comments - PER.\n",
    "\n",
    "#### __init__\n",
    "\n",
    "Here, we use PrioritizedReplayBuffer, instead of ReplayBuffer, and use hold 2 more parameters beta and priority epsilon which are used to calculate weights and new priorities respectively.\n",
    "\n",
    "#### compute_dqn_loss & update_model\n",
    "\n",
    "It returns every loss per each sample for importance sampling before average. After updating the nework, it is necessary to update priorities of all sampled experiences.\n",
    "\n",
    "#### train\n",
    "\n",
    "beta linearly increases to 1 at every training step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DQNAgent:\n",
    "    \"\"\"DQN Agent interacting with environment.\n",
    "    \n",
    "    Attribute:\n",
    "        env (gym.Env): openAI Gym environment\n",
    "        memory (ReplayBuffer): replay memory to store transitions\n",
    "        batch_size (int): batch size for sampling\n",
    "        epsilon (float): parameter for epsilon greedy policy\n",
    "        epsilon_decay (float): step size to decrease epsilon\n",
    "        max_epsilon (float): max value of epsilon\n",
    "        min_epsilon (float): min value of epsilon\n",
    "        target_update (int): period for target model's hard update\n",
    "        gamma (float): discount factor\n",
    "        dqn (Network): model to train and select actions\n",
    "        dqn_target (Network): target model to update\n",
    "        optimizer (torch.optim): optimizer for training dqn\n",
    "        transition (list): transition information including \n",
    "                           state, action, reward, next_state, done\n",
    "        beta (float): determines how much importance sampling is used\n",
    "        prior_eps (float): guarantees every transition can be sampled\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        env: gym.Env,\n",
    "        memory_size: int,\n",
    "        batch_size: int,\n",
    "        target_update: int,\n",
    "        epsilon_decay: float,\n",
    "        max_epsilon: float = 1.0,\n",
    "        min_epsilon: float = 0.1,\n",
    "        gamma: float = 0.99,\n",
    "        # PER parameters\n",
    "        alpha: float = 0.2,\n",
    "        beta: float = 0.6,\n",
    "        prior_eps: float = 1e-6,\n",
    "    ):\n",
    "        \"\"\"Initialization.\n",
    "        \n",
    "        Args:\n",
    "            env (gym.Env): openAI Gym environment\n",
    "            memory_size (int): length of memory\n",
    "            batch_size (int): batch size for sampling\n",
    "            target_update (int): period for target model's hard update\n",
    "            epsilon_decay (float): step size to decrease epsilon\n",
    "            lr (float): learning rate\n",
    "            max_epsilon (float): max value of epsilon\n",
    "            min_epsilon (float): min value of epsilon\n",
    "            gamma (float): discount factor\n",
    "            alpha (float): determines how much prioritization is used\n",
    "            beta (float): determines how much importance sampling is used\n",
    "            prior_eps (float): guarantees every transition can be sampled\n",
    "        \"\"\"\n",
    "        obs_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.n\n",
    "        \n",
    "        self.env = env\n",
    "        \n",
    "        self.batch_size = batch_size\n",
    "        self.epsilon = max_epsilon\n",
    "        self.epsilon_decay = epsilon_decay\n",
    "        self.max_epsilon = max_epsilon\n",
    "        self.min_epsilon = min_epsilon\n",
    "        self.target_update = target_update\n",
    "        self.gamma = gamma\n",
    "        \n",
    "        # device: cpu / gpu\n",
    "        self.device = torch.device(\n",
    "            \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "        )\n",
    "        print(self.device)\n",
    "        \n",
    "        # PER\n",
    "        # In DQN, We used \"ReplayBuffer(obs_dim, memory_size, batch_size)\"\n",
    "        self.beta = beta\n",
    "        self.prior_eps = prior_eps\n",
    "        self.memory = PrioritizedReplayBuffer(\n",
    "            obs_dim, memory_size, batch_size, alpha\n",
    "        )\n",
    "\n",
    "        # networks: dqn, dqn_target\n",
    "        self.dqn = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "        self.dqn_target.eval()\n",
    "        \n",
    "        # optimizer\n",
    "        self.optimizer = optim.Adam(self.dqn.parameters())\n",
    "\n",
    "        # transition to store in memory\n",
    "        self.transition = list()\n",
    "        \n",
    "        # mode: train / test\n",
    "        self.is_test = False\n",
    "\n",
    "    def select_action(self, state: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Select an action from the input state.\"\"\"\n",
    "        # epsilon greedy policy\n",
    "        if self.epsilon > np.random.random():\n",
    "            selected_action = self.env.action_space.sample()\n",
    "        else:\n",
    "            selected_action = self.dqn(\n",
    "                torch.FloatTensor(state).to(self.device)\n",
    "            ).argmax()\n",
    "            selected_action = selected_action.detach().cpu().numpy()\n",
    "        \n",
    "        if not self.is_test:\n",
    "            self.transition = [state, selected_action]\n",
    "        \n",
    "        return selected_action\n",
    "\n",
    "    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool]:\n",
    "        \"\"\"Take an action and return the response of the env.\"\"\"\n",
    "        next_state, reward, done, _ = self.env.step(action)\n",
    "\n",
    "        if not self.is_test:\n",
    "            self.transition += [reward, next_state, done]\n",
    "            self.memory.store(*self.transition)\n",
    "    \n",
    "        return next_state, reward, done\n",
    "\n",
    "    def update_model(self) -> torch.Tensor:\n",
    "        \"\"\"Update the model by gradient descent.\"\"\"\n",
    "        # PER needs beta to calculate weights\n",
    "        samples = self.memory.sample_batch(self.beta)\n",
    "        weights = torch.FloatTensor(\n",
    "            samples[\"weights\"].reshape(-1, 1)\n",
    "        ).to(self.device)\n",
    "        indices = samples[\"indices\"]\n",
    "\n",
    "        # PER: importance sampling before average\n",
    "        elementwise_loss = self._compute_dqn_loss(samples)\n",
    "        loss = torch.mean(elementwise_loss * weights)\n",
    "\n",
    "        self.optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        self.optimizer.step()\n",
    "        \n",
    "        # PER: update priorities\n",
    "        loss_for_prior = elementwise_loss.detach().cpu().numpy()\n",
    "        new_priorities = loss_for_prior + self.prior_eps\n",
    "        self.memory.update_priorities(indices, new_priorities)\n",
    "\n",
    "        return loss.item()\n",
    "        \n",
    "    def train(self, num_frames: int, plotting_interval: int = 200):\n",
    "        \"\"\"Train the agent.\"\"\"\n",
    "        self.is_test = False\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        update_cnt = 0\n",
    "        epsilons = []\n",
    "        losses = []\n",
    "        scores = []\n",
    "        score = 0\n",
    "\n",
    "        for frame_idx in range(1, num_frames + 1):\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "            \n",
    "            # PER: increase beta\n",
    "            fraction = min(frame_idx / num_frames, 1.0)\n",
    "            self.beta = self.beta + fraction * (1.0 - self.beta)\n",
    "\n",
    "            # if episode ends\n",
    "            if done:\n",
    "                state = self.env.reset()\n",
    "                scores.append(score)\n",
    "                score = 0\n",
    "\n",
    "            # if training is ready\n",
    "            if len(self.memory) >= self.batch_size:\n",
    "                loss = self.update_model()\n",
    "                losses.append(loss)\n",
    "                update_cnt += 1\n",
    "                \n",
    "                # linearly decrease epsilon\n",
    "                self.epsilon = max(\n",
    "                    self.min_epsilon, self.epsilon - (\n",
    "                        self.max_epsilon - self.min_epsilon\n",
    "                    ) * self.epsilon_decay\n",
    "                )\n",
    "                epsilons.append(self.epsilon)\n",
    "                \n",
    "                # if hard update is needed\n",
    "                if update_cnt % self.target_update == 0:\n",
    "                    self._target_hard_update()\n",
    "\n",
    "            # plotting\n",
    "            if frame_idx % plotting_interval == 0:\n",
    "                self._plot(frame_idx, scores, losses, epsilons)\n",
    "                \n",
    "        self.env.close()\n",
    "                \n",
    "    def test(self) -> None:\n",
    "        \"\"\"Test the agent.\"\"\"\n",
    "        self.is_test = True\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        done = False\n",
    "        score = 0\n",
    "        \n",
    "        while not done:\n",
    "            self.env.render()\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "        \n",
    "        print(\"score: \", score)\n",
    "        self.env.close()\n",
    "\n",
    "    def _compute_dqn_loss(self, samples: Dict[str, np.ndarray]) -> torch.Tensor:\n",
    "        \"\"\"Return dqn loss.\"\"\"\n",
    "        device = self.device  # for shortening the following lines\n",
    "        state = torch.FloatTensor(samples[\"obs\"]).to(device)\n",
    "        next_state = torch.FloatTensor(samples[\"next_obs\"]).to(device)\n",
    "        action = torch.LongTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n",
    "        reward = torch.FloatTensor(samples[\"rews\"].reshape(-1, 1)).to(device)\n",
    "        done = torch.FloatTensor(samples[\"done\"].reshape(-1, 1)).to(device)\n",
    "\n",
    "        # G_t   = r + gamma * v(s_{t+1})  if state != Terminal\n",
    "        #       = r                       otherwise\n",
    "        curr_q_value = self.dqn(state).gather(1, action)\n",
    "        next_q_value = self.dqn_target(\n",
    "            next_state\n",
    "        ).max(dim=1, keepdim=True)[0].detach()\n",
    "        mask = 1 - done\n",
    "        target = (reward + self.gamma * next_q_value * mask).to(self.device)\n",
    "\n",
    "        # calculate element-wise dqn loss\n",
    "        elementwise_loss = F.smooth_l1_loss(curr_q_value, target, reduction=\"none\")\n",
    "\n",
    "        return elementwise_loss\n",
    "    \n",
    "    def _target_hard_update(self):\n",
    "        \"\"\"Hard update: target <- local.\"\"\"\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "                \n",
    "    def _plot(\n",
    "        self, \n",
    "        frame_idx: int, \n",
    "        scores: List[float], \n",
    "        losses: List[float], \n",
    "        epsilons: List[float],\n",
    "    ):\n",
    "        \"\"\"Plot the training progresses.\"\"\"\n",
    "        clear_output(True)\n",
    "        plt.figure(figsize=(20, 5))\n",
    "        plt.subplot(131)\n",
    "        plt.title('frame %s. score: %s' % (frame_idx, np.mean(scores[-10:])))\n",
    "        plt.plot(scores)\n",
    "        plt.subplot(132)\n",
    "        plt.title('loss')\n",
    "        plt.plot(losses)\n",
    "        plt.subplot(133)\n",
    "        plt.title('epsilons')\n",
    "        plt.plot(epsilons)\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Environment\n",
    "\n",
    "You can see the [code](https://github.com/openai/gym/blob/master/gym/envs/classic_control/cartpole.py) and [configurations](https://github.com/openai/gym/blob/master/gym/envs/__init__.py#L53) of CartPole-v0 from OpenAI's repository."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# environment\n",
    "env_id = \"CartPole-v0\"\n",
    "env = gym.make(env_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set random seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[777]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seed = 777\n",
    "\n",
    "def seed_torch(seed):\n",
    "    torch.manual_seed(seed)\n",
    "    if torch.backends.cudnn.enabled:\n",
    "        torch.backends.cudnn.benchmark = False\n",
    "        torch.backends.cudnn.deterministic = True\n",
    "\n",
    "np.random.seed(seed)\n",
    "random.seed(seed)\n",
    "seed_torch(seed)\n",
    "env.seed(seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda\n"
     ]
    }
   ],
   "source": [
    "# parameters\n",
    "num_frames = 20000\n",
    "memory_size = 2000\n",
    "batch_size = 32\n",
    "target_update = 100\n",
    "epsilon_decay = 1 / 2000\n",
    "\n",
    "# train\n",
    "agent = DQNAgent(env, memory_size, batch_size, target_update, epsilon_decay)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "agent.train(num_frames)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test\n",
    "\n",
    "Run the trained agent (1 episode)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "score:  200.0\n"
     ]
    }
   ],
   "source": [
    "agent.env = gym.wrappers.Monitor(env, \"videos\", force=True)\n",
    "agent.test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Render"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "videos/openaigym.video.0.13364.video000000.mp4\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "        <video alt=\"test\" controls>\n",
       "        <source src=\"data:video/mp4;base64,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AgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAAAwAAAAABAAABAAAAAAEAAAMAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAEAAAAAAIAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAUAAAAAAQAAAgAAAAABAAAAAAAAAAEAAAEAAAAAAQAABQAAAAABAAACAAAAAAEAAAAAAAAAAQAAAQAAAAABAAAFAAAAAAEAAAIAAAAAAQAAAAAAAAABAAABAAAAAAEAAAIAAAAAHHN0c2MAAAAAAAAAAQAAAAEAAADJAAAAAQAAAzhzdHN6AAAAAAAAAAAAAADJAAAEUQAAAHwAAAA8AAAAMgAAADcAAACjAAAAQgAAAIIAAABGAAAAMQAAACwAAABvAAAAOAAAADoAAAAxAAAAVgAAAE8AAAAuAAAAMQAAAHAAAABBAAAAUwAAAEEAAAA2AAAAJAAAAG0AAAAyAAAAMwAAAC4AAABYAAAAPQAAAD0AAAAjAAAAXgAAAEMAAAAnAAAAJQAAAF4AAAAsAAAAMgAAADAAAABLAAAANwAAACgAAAAjAAAASAAAAEUAAAAtAAAANgAAAFYAAABFAAAAJgAAAB4AAABdAAAAQQAAACAAAAAnAAAARAAAACUAAAAmAAAALgAAAFoAAAA3AAAAJAAAADIAAABDAAAAQQAAACwAAAA4AAAARwAAAEoAAAAlAAAAHQAAAGIAAAA4AAAAIgAAACEAAABeAAAAKAAAADEAAAAiAAAAXQAAAEcAAAAxAAAAJgAAAG0AAABQAAAAJwAAAEwAAABZAAAAPQAAAE0AAAA5AAAAWwAAAEoAAAA8AAAAPwAAAGkAAABGAAAAPgAAAC0AAAA2AAAAOgAAACYAAAAlAAAASQAAADcAAAApAAAANgAAAKoAAABSAAAANwAAACsAAAB/AAAAbAAAAEsAAABCAAAAYgAAAD4AAAApAAAARAAAAFgAAABLAAAAOwAAACMAAABAAAAANQAAACcAAAA8AAAAPwAAADgAAAAkAAAAMAAAAEgAAABOAAAAHAAAACkAAABiAAAANAAAACEAAABKAAAAUwAAADAAAAAhAAAAGwAAAHoAAABQAAAAJAAAAEYAAABXAAAAQwAAAEcAAAAyAAAAUwAAACwAAAAyAAAAVgAAAC8AAAAzAAAAMAAAAD0AAAAlAAAAPAAAACMAAAAwAAAAKQAAAC4AAAAxAAAAPgAAAEkAAAAwAAAAKQAAAGQAAABDAAAAKAAAACoAAABlAAAAPAAAACYAAAAlAAAAQAAAACgAAAAiAAAALgAAAFQAAAA9AAAAIQAAADcAAABlAAAARAAAAEMAAAA3AAAANgAAAEIAAAA9AAAAUwAAADUAAABAAAAAPgAAACoAAAA0AAAAFHN0Y28AAAAAAAAAAQAAADAAAABidWR0YQAAAFptZXRhAAAAAAAAACFoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAC1pbHN0AAAAJal0b28AAAAdZGF0YQAAAAEAAAAATGF2ZjU3LjgzLjEwMA==\" type=\"video/mp4\" />\n",
       "        </video>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import base64\n",
    "import glob\n",
    "import io\n",
    "import os\n",
    "\n",
    "from IPython.display import HTML, display\n",
    "\n",
    "\n",
    "def ipython_show_video(path: str) -> None:\n",
    "    \"\"\"Show a video at `path` within IPython Notebook.\"\"\"\n",
    "    if not os.path.isfile(path):\n",
    "        raise NameError(\"Cannot access: {}\".format(path))\n",
    "\n",
    "    video = io.open(path, \"r+b\").read()\n",
    "    encoded = base64.b64encode(video)\n",
    "\n",
    "    display(HTML(\n",
    "        data=\"\"\"\n",
    "        <video alt=\"test\" controls>\n",
    "        <source src=\"data:video/mp4;base64,{0}\" type=\"video/mp4\"/>\n",
    "        </video>\n",
    "        \"\"\".format(encoded.decode(\"ascii\"))\n",
    "    ))\n",
    "\n",
    "list_of_files = glob.glob(\"videos/*.mp4\")\n",
    "latest_file = max(list_of_files, key=os.path.getctime)\n",
    "print(latest_file)\n",
    "ipython_show_video(latest_file)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
